{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import os\n",
    "import json\n",
    "\n",
    "from statsmodels import api as sm\n",
    "from scipy.stats import pearsonr\n",
    "import scipy.signal as signal"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def isPeriodic(tempNorm):\n",
    "    periodFlag = 0\n",
    "    try:\n",
    "        acf = sm.tsa.acf(tempNorm, nlags=len(tempNorm)) # 计算自相关系数\n",
    "\n",
    "        peak_ind = signal.argrelextrema(acf, np.greater)[0] # 寻找局部峰值\n",
    "        fwbest = acf[signal.argrelextrema(acf, np.greater)]\n",
    "\n",
    "        index = -1\n",
    "        ran = 0\n",
    "        fwbestlen = len(fwbest)\n",
    "        if fwbestlen == 0:\n",
    "            periodFlag = 0\n",
    "            return periodFlag\n",
    "        \n",
    "        for i in range(ran, fwbestlen):\n",
    "            if fwbest[i] > 0:\n",
    "                j = i\n",
    "                while fwbest[j] > 0:\n",
    "                    j += 1\n",
    "                    if j > fwbestlen - 1:\n",
    "                        periodFlag = 1\n",
    "                        return periodFlag\n",
    "                index = (i + j - 1) // 2\n",
    "                break\n",
    "\n",
    "        fd = peak_ind[index] # 频率\n",
    "        numlist = []\n",
    "        Q = len(tempNorm) // fd # 周期\n",
    "        if Q == 1:\n",
    "            periodFlag = 0\n",
    "            return periodFlag\n",
    "        else:\n",
    "            for i in range(Q): # 分段\n",
    "                numlist.append(tempNorm[i * fd: (i + 1) * fd])\n",
    "\n",
    "            listlen = len(numlist) # 段数\n",
    "            flag = 0\n",
    "            for i in range(1, listlen):\n",
    "                a = pearsonr(numlist[i-1], numlist[i])[0] # 相邻两段的皮尔森系数\n",
    "                if a < 0.85:\n",
    "                    flag += 1 # 小于阈值的数量\n",
    "\n",
    "            if flag <= listlen // 3: # 小于阈值的低于总段数的1/3\n",
    "                periodFlag = 1\n",
    "                return periodFlag\n",
    "            else:\n",
    "                periodFlag = 0\n",
    "                return periodFlag\n",
    "\n",
    "    except Exception as e:\n",
    "        print(f\"处理数据时出现错误：{str(e)}\")\n",
    "        return periodFlag"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 曲线平滑处理\n",
    "def Smooth(ts):\n",
    "    dif = ts.diff().dropna() # 差分序列，1-69119行\n",
    "    td = dif.describe() # 描述性统计得到：min，25%，50%，75%，max值\n",
    "    \n",
    "    high = td['75%'] + 1.5 * (td['75%'] - td['25%']) # 定义高点阈值，1.5倍四分位距之外\n",
    "    low = td['25%'] - 1.5 * (td['75%'] - td['25%']) # 定义低点阈值，同上\n",
    "    \n",
    "    # 变化幅度超过阈值的点的索引\n",
    "    forbid_index = dif[(dif > high) | (dif < low)].index \n",
    "    i = 0\n",
    "    while i < len(forbid_index) - 1:\n",
    "        n = 1 # 发现连续多少个点变化幅度过大，大部分只有单个点\n",
    "        start = forbid_index[i] # 异常点的起始索引\n",
    "        while (i+n)<len(forbid_index) and forbid_index[i+n] == start + n:\n",
    "            n += 1\n",
    "        i += n - 1\n",
    "    \n",
    "        end = forbid_index[i] # 异常点的结束索引\n",
    "        # 用前后值的中间值均匀填充\n",
    "        value = np.linspace(ts[start-1], ts[end+1], n) # 创建等差数列\n",
    "        ts[start:end+1] = value\n",
    "        i += 1\n",
    "        \n",
    "    return ts"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def process_container_utilization(containerUtilDict, batch_size=100):\n",
    "    nonperiodic_cpu = pd.DataFrame(columns=['id'])\n",
    "    periodic_cpu = pd.DataFrame(columns=['id'])\n",
    "    nonperiodic_mem = pd.DataFrame(columns=['id'])\n",
    "    periodic_mem = pd.DataFrame(columns=['id'])\n",
    "\n",
    "    # 分批处理数据\n",
    "    for batch_start in range(0, len(containerUtilDict), batch_size):\n",
    "        batch_end = min(batch_start + batch_size, len(containerUtilDict))\n",
    "        batch_dict = {k: containerUtilDict[k] for k in list(containerUtilDict.keys())[batch_start:batch_end]}\n",
    "        \n",
    "        for cid, utilList in batch_dict.items():\n",
    "            try:\n",
    "                cpu_list = [util[0] for util in utilList]\n",
    "                mem_list = [util[1] for util in utilList]\n",
    "                \n",
    "                #平滑处理\n",
    "                cpu_smoothed = Smooth(pd.Series(cpu_list))\n",
    "                mem_smoothed = Smooth(pd.Series(mem_list))\n",
    "                \n",
    "                # 判断周期性\n",
    "                flag_cpu = isPeriodic(cpu_smoothed.values.tolist())\n",
    "                if flag_cpu == 0:\n",
    "                    nonperiodic_cpu.loc[len(nonperiodic_cpu)] = [cid]\n",
    "                elif flag_cpu == 1:\n",
    "                    periodic_cpu.loc[len(periodic_cpu)] = [cid]\n",
    "                    \n",
    "                flag_mem = isPeriodic(mem_smoothed.values.tolist())\n",
    "                if flag_mem == 0:\n",
    "                    nonperiodic_mem.loc[len(nonperiodic_mem)] = [cid]\n",
    "                elif flag_mem == 1:\n",
    "                    periodic_mem.loc[len(periodic_mem)] = [cid]\n",
    "            \n",
    "            except Exception as e:\n",
    "                print(f\"处理容器 {cid} 时出错：{str(e)}\")\n",
    "\n",
    "    return nonperiodic_cpu, periodic_cpu, nonperiodic_mem, periodic_mem"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "if __name__ == '__main__':\n",
    "    try:\n",
    "        with open('../containerUtilDict.txt', 'r') as file:\n",
    "            containerUiltDict = json.load(file)\n",
    "        print('加载容器资源消耗序列字典成功')\n",
    "        \n",
    "        # 处理容器资源利用率数据\n",
    "        nonperiodic_cpu, periodic_cpu, nonperiodic_mem, periodic_mem = process_container_utilization(containerUiltDict)\n",
    "        \n",
    "        # 打印结果或做进一步处理\n",
    "        print(\"非周期性 CPU 容器:\", nonperiodic_cpu)\n",
    "        print(\"周期性 CPU 容器:\", periodic_cpu)\n",
    "        print(\"非周期性 内存 容器:\", nonperiodic_mem)\n",
    "        print(\"周期性 内存 容器:\", periodic_mem)\n",
    "        \n",
    "    except FileNotFoundError:\n",
    "        print(\"文件 containerUtilDict.txt 未找到。\")\n",
    "    except json.JSONDecodeError:\n",
    "        print(\"解析 JSON 数据时出错。\")\n",
    "    except Exception as e:\n",
    "        print(f\"发生未知错误：{str(e)}\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "tetris",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.18"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
